package com.plian.system.service.pf.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.config.exception.MyRuntimeException;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.dto.pf.BusinessResponsibilityDTO;
import com.plian.system.entity.pf.BusinessResponsibility;
import com.plian.system.enumeratea.BusinessIndicatorsStatus;
import com.plian.system.mapper.pf.BusinessResponsibilityMapper;
import com.plian.system.model.ObjResult;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.pf.IBaseBusinessIndicatorsService;
import com.plian.system.service.pf.IBusinessReplenishChangeService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.pf.BaseBusinessIndicatorsVO;
import com.plian.system.vo.pf.BusinessResponsibilityVO;
import com.plian.system.wrapper.pf.BusinessResponsibilityWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * @Author: Take-off
 * @Description: TODO
 * @Date: 2022/12/20 3:05 PM
 * @Version: 1.0
 **/
@Service
@AllArgsConstructor
public class BusinessResponsibilityChangeServiceImpl extends BaseServiceImpl<BusinessResponsibilityMapper, BusinessResponsibility> implements IBusinessReplenishChangeService, BaseFlowService {

    private final IBaseBusinessIndicatorsService baseBusinessIndicatorsService;

    private final FormWorkflowService formWorkflowService;

    private final IFormCodeService formCodeService;

    private final BusinessResponsibilityWrapper businessResponsibilityWrapper;


    /**
     * @Author: Take-off
     * @Description: //TODO 返回指标数据
     * @Date: 4:04 PM 2022/12/20
     * @Param: [dto]
     * @return: com.plian.system.vo.pf.BusinessResponsibilityVO
     **/
    @Override
    public BusinessResponsibilityVO getDocData(BusinessResponsibilityDTO dto){
        BusinessResponsibilityVO businessResponsibilityVO = new BusinessResponsibilityVO();
        BaseBusinessIndicatorsVO indicatorsVO = baseBusinessIndicatorsService.getDetailByDto(dto.getFillingYear(), dto.getFillingUnitId());
        if (Optional.ofNullable(indicatorsVO).isPresent()){
            businessResponsibilityVO.setFillingUnitName(indicatorsVO.getFillingUnitName());
            businessResponsibilityVO.setFillingYear(indicatorsVO.getFillingYear());
            businessResponsibilityVO.setBusinessIndicatorsVOS(indicatorsVO.getBusinessIndicatorsVOS());
            businessResponsibilityVO.setTaskIndicatorsVOS(indicatorsVO.getTaskIndicatorsVOS());
        }
        return businessResponsibilityVO;
    }

    @Override
    public boolean saveOrUpdate(BusinessResponsibility businessResponsibility) {

        if (!Optional.ofNullable(businessResponsibility.getStatus()).isPresent()) {
            businessResponsibility.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (businessResponsibility.getStatus().equals(FormStatusConstant.REJECT)) {
            businessResponsibility.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (!Optional.ofNullable(businessResponsibility.getId()).isPresent()) {
            businessResponsibility.setCode(formCodeService.getCode(FormTypeConstant.PF_BUSINESS_RESPONSIBILITY_CHANGE));
            businessResponsibility.setFormType(String.valueOf(FormTypeConstant.PF_BUSINESS_RESPONSIBILITY_CHANGE));
            businessResponsibility.setVersion(businessResponsibility.getVersion() + 1);
            businessResponsibility.setIsLatest(1);
            businessResponsibility.setIndicatorStatus(BusinessIndicatorsStatus.CHANGE_AUDIT.getStatus());
            businessResponsibility.setInitialId(businessResponsibility.getInitialId());
            businessResponsibility.setIssued(1);
            updateLangStatus(businessResponsibility.getInitialId(), BusinessIndicatorsStatus.CHANGE_AUDIT.getStatus());
        }

        return super.saveOrUpdate(businessResponsibility);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            BusinessResponsibility businessResponsibility = getById(id);
            if (businessResponsibility == null) {
                return false;
            } else if (businessResponsibility.getStatus() != null &&
                    (businessResponsibility.getStatus() != FormStatusConstant.STASH && businessResponsibility.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            updateLangStatus(businessResponsibility.getInitialId(), BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
            update(Wrappers.<BusinessResponsibility>lambdaUpdate()
                    .eq(BusinessResponsibility::getInitialId, businessResponsibility.getInitialId())
                    .eq(BusinessResponsibility::getVersion, businessResponsibility.getVersion() - 1)
                    .set(BusinessResponsibility::getIsLatest, 2));

            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }
        boolean result = super.deleteLogic(ids);
        return result;
    }

    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        BusinessResponsibility responsibility = getById(id);
        updateLangStatus(responsibility.getInitialId(), BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
        updateIsLatest(responsibility.getInitialId());
        responsibility.setApprovedUser(TokenUtil.getTokenUserId());
        Date now = DateUtil.now();
        responsibility.setApprovedTime(now);
        responsibility.setIsLatest(2);
        responsibility.setIndicatorStatus(BusinessIndicatorsStatus.ADJUSTABLE.getStatus());
        updateById(responsibility);

        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState);
    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id          主键
     * @param updateStatus  更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus) {
        try {
            BusinessResponsibility businessResponsibility = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH){
                businessResponsibility.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                businessResponsibility.setApprovedTime(now);
            }
            businessResponsibility.setStatus(updateStatus);
            updateById(businessResponsibility);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }


    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<BusinessResponsibility> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BusinessResponsibility::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<BusinessResponsibility> businessResponsibilities = list(queryWrapper);
        List<BusinessResponsibilityVO> businessResponsibilityVOS = businessResponsibilityWrapper.entityToVO(businessResponsibilities);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(businessResponsibilityVOS)){
                for (BusinessResponsibilityVO vo : businessResponsibilityVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getFillingUnitName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getFillingUnitId());
                    pd.put("formType", FormTypeConstant.PF_BUSINESS_RESPONSIBILITY_CHANGE);
                    pd.put("orgName", vo.getFillingUnitName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.PF_BUSINESS_RESPONSIBILITY_CHANGE);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean submit(BusinessResponsibility businessResponsibility) {
        boolean result = saveOrUpdate(businessResponsibility);
        return result;
    }

    @Override
    public void goBackToStash(String formId) {
        Long id = Long.valueOf(formId);
        BusinessResponsibility responsibility = getById(id);
        if (responsibility.getStatus() == FormStatusConstant.FINISH){
            if (responsibility.getIsLatest() != null && responsibility.getIsLatest() != 2){
                throw new MyRuntimeException(new ObjResult("该指标信息不是最新  不可回退！"));
            }
            LambdaUpdateWrapper<BusinessResponsibility> updateWrapper = new LambdaUpdateWrapper<>();
            update(updateWrapper.eq(BusinessResponsibility::getId, id)
                    .set(BusinessResponsibility::getApprovedUser, null).set(BusinessResponsibility::getApprovedTime, null));
            updateLangStatus(responsibility.getInitialId(), BusinessIndicatorsStatus.CHANGE_AUDIT.getStatus());
            updateIsLatest(responsibility.getInitialId());
            List<BusinessResponsibility> businessResponsibilities = list(new LambdaUpdateWrapper<BusinessResponsibility>().eq(BusinessResponsibility::getInitialId, id)
                    .orderByDesc(BusinessResponsibility::getVersion));
            if (CollectionUtil.isNotEmpty(businessResponsibilities) && businessResponsibilities.size() > 1){
                BusinessResponsibility businessResponsibility = businessResponsibilities.get(1);
                businessResponsibility.setIsLatest(2);
                updateById(businessResponsibility);
            }
        }

        handleStatus(Long.valueOf(formId), UNREVIEWED);
    }


    private void updateLangStatus(Long initialId, int landStatus){
        update(new LambdaUpdateWrapper<BusinessResponsibility>().eq(BusinessResponsibility::getInitialId, initialId).set(BusinessResponsibility::getIndicatorStatus, landStatus));
    }

    private void updateIsLatest(Long initialId){
        update(new LambdaUpdateWrapper<BusinessResponsibility>().eq(BusinessResponsibility::getInitialId, initialId)
                .eq(BusinessResponsibility::getIsLatest, 2).set(BusinessResponsibility::getIsLatest, 1));
    }

}
